package cn.cl.registery;


import cn.cl.CurtorConfig;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class RegisteryClient {
    private static volatile CuratorFramework zkClient;
    //父节点
    protected static final String PATH = "/servers";

    //缓存的服务集合
    protected static final List<String> servers = new ArrayList<>();

    public void initCollection() {
        if (zkClient == null) {
            synchronized (RegisteryClient.class) {
                if (zkClient == null) {
                    zkClient = CuratorFrameworkFactory.builder()
                            .connectString(CurtorConfig.ADDRESS)
                            // 会话超时时间
                            .sessionTimeoutMs(5000)
                            .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                            .build();
                    zkClient.start();
                    initListener();
                }
            }
        }

    }

    /**
     * 向注册中心注册节点
     * @param hostName
     */
    public void registery(String hostName) {
        try {
            zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(PATH + "/node",hostName.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 缓存所有服务到本地
     */
    public void loadServers() {
        try {
            List<String> childs = zkClient.getChildren().forPath(PATH);
            if (childs != null && childs.size() > 0) {
                for (String child : childs) {
                    byte[] data = zkClient.getData().forPath(PATH + "/" + child);
                    servers.add(new String(data));
                }
            }

            for (String server : servers) {
                System.out.println("server:" + server);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 监听服务的上下线
     */
    public void initListener() {
        try {
            PathChildrenCache cache = new PathChildrenCache(zkClient,PATH,true);
            cache.getListenable().addListener(new PathChildrenCacheListener() {
                @Override
                public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                    if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(event.getType()) || PathChildrenCacheEvent.Type.CHILD_ADDED.equals(event.getType())) {
                        //重新缓存本地的服务
                        loadServers();
                    }
                }
            });
            cache.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        RegisteryClient client = new RegisteryClient();
        client.initCollection();
        client.loadServers();
        client.registery("343566666");
        client.doWork();
    }

    private void doWork() {
        System.out.println("client working");
        try {
            Thread.sleep(Long.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}